﻿#include"stdafx.h"
#ifdef LK_FUNCTIONAL_
namespace LK
{
	namespace Functional
	{
		/**
		@brief 添加一个函数对象*/
		PDelegates& PDelegates::operator+=(PFunObjs const&d) { if (!d.IsNull()) { if (IsNull())return *this = d; *GetPtr() += *d.GetPtr(); }return*this; }
		/**
		@brief 移除一个函数对象*/
		PDelegates& PDelegates::operator-=(PFunObjs const&d) { if (!d.IsNull() && !IsNull())*GetPtr() -= *d.GetPtr(); return*this; }
		/**
		@brief 从函数对象构造*/
		PDelegates::PDelegates(PFunObjs const&f) :PObject(new IDelegates(f)) {}
		/**
		@brief 传入PObject封装的参数并进行多播调用*/
		PObject PDelegates::Invoke(PObject const& obj, Collection::PArray<PObject>args)const
		{
			return Ptr()->Invoke(obj, args);
		}
		/**
		@brief 添加一个委托*/
		PDelegates& PDelegates::operator+=(PDelegates const&d) { if (!d.IsNull()) { if (IsNull())return *this = d; *GetPtr() += *d.GetPtr(); }return*this; }
		/**
		@brief 移除一个委托*/
		PDelegates& PDelegates::operator-=(PDelegates const&d) { if (!d.IsNull() && !IsNull())*GetPtr() -= *d.GetPtr(); return*this; }
		/**
		@brief 获取函数对象数组的引用*/
		Collection::PArray<PFunObjs>& PDelegates::GetFunObjsArrayRef()const { return Ptr()->funarr; }
		/**
		@brief 添加一个委托*/
		IDelegates& IDelegates::operator+=(IDelegates &d)
		{
			if (d.funarr.IsNull())return*this;
			if (funarr.IsNull())funarr = d.funarr->Clone();
			else if ((void*)&(void*&)d == this)
				funarr.AppendArray(d.funarr);
			else
			{
				//类型检查
				using namespace Collection;
				PArray<PType> check = funarr.FirstElement().GetArgsType();
				PArray<PType> ch = d.funarr.FirstElement().GetArgsType();
				if (check.size() != ch.size())throw PFunctionalException(L"检测到+=的委托参数数量不一致：应传入" + PString(check.size() - 2) + L"个参数的委托，但传入的委托为 " + PString(ch.size() - 2) + L"个参数");
				if (check[0] != ch[0])throw PFunctionalException(L"检测到+=的委托的返回值类型不一致：原委托返回类型是 " + check[0].GetName() + L"，但传入委托的返回值类型是 " + ch[0].GetName());
				for (index_t i = 2; i < check.size(); ++i)if (check[i] != ch[i])throw PFunctionalException(L"检测到传入委托的第" + PString(i - 1) + L"个参数类型不一致：原委托参数类型是 " + check[i].GetName() + L"，但传入的委托参数类型是 " + ch[i].GetName());
				funarr.AppendArray(d.funarr);
			}
			return *this;
		}
		/**
		@brief 移除一个委托*/
		IDelegates& IDelegates::operator-=(IDelegates &d)
		{
			if (d.funarr.IsNull() || funarr.IsNull())return*this;
			if ((void*)&(void*&)d == this)
				funarr.SetToNull();
			else
			{
				index_t i = 0;
				index_t len = d.funarr.size();
				while (i < len)
				{
					PFunObjs f = d.funarr[i];
					index_t j = 0;
					index_t tlen = funarr.size();
					PFunObjs* p = funarr;
					while (j < tlen&&!p[j].Equals(f))++j;
					if (j < tlen) { funarr.RemoveAt(j); if (tlen == 1)break; }
					++i;
				}
			}
			return *this;
		}
		/**
		@brief 添加一个函数对象*/
		IDelegates& IDelegates::operator+=(IFunObjs &d)
		{
			if (funarr.IsNull())funarr = new LK::Collection::DefaultArray<PFunObjs>(1, d.Clone());
			else {
				//类型检查不通过
				using namespace Collection;
				PArray<PType> check = funarr.FirstElement().GetArgsType();
				PArray<PType> ch = d.GetArgsType();
				if (check.size() != ch.size())throw PFunctionalException(L"检测到+=的委托参数数量不一致：应传入" + PString(check.size() - 2) + L"个参数的委托，但传入的委托为 " + PString(ch.size() - 2) + L"个参数");
				if (check[0] != ch[0])throw PFunctionalException(L"检测到+=的委托的返回值类型不一致：原委托返回类型是 " + check[0].GetName() + L"，但传入委托的返回值类型是 " + ch[0].GetName());
				for (index_t i = 2; i < check.size(); ++i)if (check[i] != ch[i])throw PFunctionalException(L"检测到传入委托的第" + PString(i - 1) + L"个参数类型不一致：原委托参数类型是 " + check[i].GetName() + L"，但传入的委托参数类型是 " + ch[i].GetName());
				funarr.Append(&d);
			}
			return *this;
		}
		/**
		@brief 移除一个函数对象*/
		IDelegates& IDelegates::operator-=(IFunObjs &d)
		{
			if (funarr.IsNull())return*this;
			PFunObjs*p = funarr;
			for (index_t i = 0; i < funarr.size(); ++i)
				if (p[i].Equals(&d)) { funarr.RemoveAt(i); break; }
			return *this;
		}
	}
}
#endif